package com.csproj.basic.service;

import com.csproj.basic.BasicService;
import com.csproj.basic.domain.Site;
import com.csproj.basic.domain.Warehouse;
import com.csproj.basic.repository.SiteRepository;
import com.csproj.basic.service.dto.WarehouseDTO;
import com.csproj.basic.service.mapper.WarehouseMapper;
import com.csproj.basic.repository.WarehouseRepository;
import com.csproj.dispatch.domain.WarnInfo;
import com.csproj.siiat.base.common.dto.BaseDTO;
import com.csproj.siiat.base.common.exception.BaseAppException;
import com.csproj.siiat.base.common.util.FileUtils;
import com.csproj.siiat.base.common.util.poi.POIUtil;
import com.csproj.siiat.security.SecurityUtils;
import com.csproj.system.domain.UserInfo;
import com.thoughtworks.xstream.security.RegExpTypePermission;
import net.logstash.logback.encoder.org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.ZonedDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Service Implementation for managing Warehouse.
 */
@Service
@Transactional
public class WarehouseService extends BasicService<WarehouseDTO> {

    private final Logger log = LoggerFactory.getLogger(WarehouseService.class);

    @Resource(name="warehouseRepository")
    private final WarehouseRepository warehouseRepository;

    private final WarehouseMapper warehouseMapper;
    @Resource(name="siteRepository")
    private final SiteRepository siteRepository;

    public WarehouseService(WarehouseRepository warehouseRepository,
                            WarehouseMapper warehouseMapper, SiteRepository siteRepository) {
        this.warehouseRepository = warehouseRepository;
        this.warehouseMapper = warehouseMapper;
        this.siteRepository = siteRepository;
    }

    /**
     * 保存机构并且返回前端需要发的dto，包括扩展属性createName
     * @param warehouseDTO
     * @return warehouseDTO
     * TODO 主要负责从前端接收值
     * TODO DTO的扩展属性，在此方法复制
     */
    public WarehouseDTO saveAndGetDTO(WarehouseDTO warehouseDTO) {
        Warehouse warehouse = warehouseMapper.toEntity(warehouseDTO);
        warehouse = save(warehouse);
        warehouseDTO = warehouseMapper.toDto(warehouse);
        return warehouseDTO;
    }

    /**
     * 保存机构
     * @param warehouse
     * @return warehouse
     * TODO 纯粹的保存方法，通用于所有保存业务调用
     * TODO 赋默认值，保存后，检查数据库，是否所有字段都有准确值
     */
    public Warehouse save(Warehouse warehouse) {
        Warehouse whName = warehouseRepository.findFirstByHouseNameAndDeletedFlagIsFalse(warehouse.getHouseName());

        if(StringUtils.isNotBlank(warehouse.getId())){
            if(whName!=null && !whName.getId().equals(warehouse.getId())) {
                throw new BaseAppException(false,"duplicate_name");
            }
        }else if(whName!=null){
            throw  new BaseAppException(false,"duplicate_name");
        }
        warehouse.setEnableFlag(true);
        warehouse.setCreationTime(ZonedDateTime.now());
        warehouse.setCreatorUserId(SecurityUtils.getCurrentUserId());
        warehouse.setDeletedFlag(false);
        return warehouseRepository.save(warehouse);
    }

    /**
     * 修改机构并且返回前端需要发的dto，包括扩展属性
     * @param warehouseDTO
     * @return warehouseDTO
     * TODO 类似SAVE
     */
    public WarehouseDTO updateAndGetDTO(WarehouseDTO warehouseDTO) {
        Warehouse warehouse = warehouseRepository.findOne(warehouseDTO.getId());
        if(warehouse == null){
            throw new BaseAppException(BaseDTO.CODE_PARAM,"id_errors");
        }
        warehouse.setHouseName(warehouseDTO.getHouseName());
        warehouse.setAddress(warehouseDTO.getAddress());
        warehouse.setLng(warehouseDTO.getLng());
        warehouse.setLat(warehouseDTO.getLat());
        warehouse.setRadius(warehouseDTO.getRadius());
        warehouse.setSiteId(warehouseDTO.getSiteId());
        warehouse.setManagerName(warehouseDTO.getManagerName());
        warehouse.setManagerPhone(warehouseDTO.getManagerPhone());
        warehouse.setHousePhone(warehouseDTO.getHousePhone());
        warehouse = update(warehouse);
        return warehouseMapper.toDto(warehouse);
    }

    /**
     * 修改机构
     * @param warehouse
     * @return warehouse
     * TODO 类似SAVE
     */
    public Warehouse update(Warehouse warehouse) {
        Warehouse whName = warehouseRepository.findFirstByHouseNameAndDeletedFlagIsFalse(warehouse.getHouseName());
        if(StringUtils.isNotBlank(warehouse.getId())){
            if(whName!=null && !whName.getId().equals(warehouse.getId())) {
                throw new BaseAppException(false,"duplicate_name");
            }

        }else if(whName!=null){
            throw  new BaseAppException(false,"duplicate_name");
        }
        Warehouse warehouseDB = findOne(warehouse.getId());
        warehouseDB.setHouseName(warehouse.getHouseName());
        warehouseDB.setAddress(warehouse.getAddress());
        warehouseDB.setRadius(warehouse.getRadius());
        warehouseDB.setLat(warehouse.getLat());
        warehouseDB.setLng(warehouse.getLng());
        warehouseDB.setSiteId(warehouse.getSiteId());
        warehouseDB.setManagerName(warehouse.getManagerName());
        warehouseDB.setManagerPhone(warehouse.getManagerPhone());
        warehouseDB.setHousePhone(warehouse.getHousePhone());

        warehouseDB.setLastModificationTime(ZonedDateTime.now());
        warehouseDB.setLastModifierUserId(SecurityUtils.getCurrentUserId());
        warehouseDB = warehouseRepository.save(warehouseDB);
        return warehouseDB;
    }




    /**
     * TODO 返回纯粹的数据库对象，不包含扩展属性，适用于所有调取业务方法
     *
     * @return the list of entities
     */
    @Transactional(readOnly = true)
    public List<Warehouse> findAll() {
        log.debug("Request to get all Warehouses");
        List<Warehouse> warehouses = warehouseRepository.findAllEnabled();
        return warehouses;
    }

    /**
     *  获取所有机构信息
     *  @return
     *  TODO 返回DTO，包含扩展属性
     *  TODO 如果扩展属性不同，可写多个findAllAndGetDTO1、findAllAndGetDTO2，注明扩展的属性
     */
    @Transactional(readOnly = true)
    public List<WarehouseDTO> findAllAndGetDTO() {
        List<WarehouseDTO> warehouseDTOs = warehouseMapper.toDto(findAll());
        return warehouseDTOs;
    }

    /**
     *  获取所有机构信息
     *  @return
     *  TODO 返回DTO，包含扩展属性
     *  TODO 如果扩展属性不同，可写多个findAllAndGetDTO1、findAllAndGetDTO2，注明扩展的属性
     */
    @Transactional(readOnly = true)
    public List<WarehouseDTO> findAllBySiteIdAndGetDTO(String siteId) {
        List<Warehouse> list = warehouseRepository.findWarehousesBySiteId(siteId);
        List<WarehouseDTO> warehouseDTOs = warehouseMapper.toDto(list);
        return warehouseDTOs;
    }

    /**
     * 根据id，获取机构信息
     *  @param id the id of the entity
     *  @return the entity
     *
     *  TODO 返回纯粹的数据库对象，不包含扩展属性，适用于所有调取业务方法
     */
    @Transactional(readOnly = true)
    public Warehouse findOne(String id) {
        Warehouse organization = warehouseRepository.findOne(id);
        if(organization == null){
            throw new BaseAppException(BaseDTO.CODE_PARAM,"id_errors");
        }
        return organization;
    }


    /**
     *  获取所有机构信息（分页）
     *  @return the list of entities
     *
     *  TODO 返回纯粹的数据库对象，不包含扩展属性，适用于所有调取业务方法
     */
    @Transactional(readOnly = true)
    public Page<Warehouse> findPageList(Map<String, Object> map, Pageable pageable) {
        Page<Warehouse> result = warehouseRepository.findPageList(map,pageable);
        return result;
    }

    /**
     *  获取所有机构信息（分页）
     *  @return the list of entities
     *
     *  TODO 返回DTO，包含扩展属性
     *  TODO 如果扩展属性不同，findPageListAndGetDTO1、findPageListAndGetDTO2，注明扩展的属性
     */
    @Transactional(readOnly = true)
    public BaseDTO findPageListAndGetDTO(Map<String,Object> map, Pageable pageable) {
        Page<Warehouse> result = findPageList(map,pageable);
        List<Warehouse> warehouses = result.getContent();
        List<WarehouseDTO> warehouseDTOS = warehouseMapper.toDto(warehouses);
        extendSiteName(warehouseDTOS);
        return BaseDTO.createBaseDTO(result).setFieldList(warehouseDTOS);
    }


    /**
     * 根据id，获取机构信息
     *  @param id 主键id
     *  @return creator、questionTypeName
     *
     *  TODO 返回DTO，包含扩展属性
     *  TODO 如果扩展属性不同，findPageListAndGetDTO1、findPageListAndGetDTO2，注明扩展的属性
     */
    @Transactional(readOnly = true)
    public WarehouseDTO findOneAndGetDTO(String id) {
        Warehouse warehouse = findOne(id);
        WarehouseDTO warehouseDTO = warehouseMapper.toDto(warehouse);
        extendSiteName(warehouseDTO);
        extendManagerName(warehouseDTO);
        return warehouseDTO;
    }

    /**
     *  根据id，删除机构信息
     *  @param id the id of the entity
     */
    public void delete(String id) {
        warehouseRepository.delete(id);
    }

    /**
     * 根据机构ids，批量删除机构信息
     * @param ids
     */
    public void deleteIds(String[] ids){
        warehouseRepository.deleteIds(ids);
    }

    /**
     * 设置仓储的使用状态：禁用，启用，默认为启用
     * @param warehouseDTO
     * @return
     */
    public WarehouseDTO updateWarehouseStatus(WarehouseDTO warehouseDTO) {
        log.debug("Request to update UserInfo isUse : {}", warehouseDTO);
        Warehouse warehouse = warehouseRepository.findOne(warehouseDTO.getId());
        Boolean isUse = warehouseDTO.getEnableFlag();
        if (isUse != null && !"".equals(isUse)) {
            warehouse.setEnableFlag(isUse);
        } else {
            warehouse.setEnableFlag(true);
        }
        warehouse.setReason(warehouseDTO.getReason());
        warehouse = warehouseRepository.save(warehouse);
        WarehouseDTO result = warehouseMapper.toDto(warehouse);
        return result;
    }

    /**
     * 上传文件
     * @param file
     */
    public String uploadFile(HttpServletRequest request, MultipartFile file){
        String filePath = FileUtils.excelUpload(request,file, File.separator+"upload"+ File.separator+"warehouse");
        return filePath;
    }

    /**
     * 批量导入
     * @param file
     * @return
     */
    public BaseDTO batchImport(MultipartFile file) {
        try {
            List<String[]> readResult = POIUtil.readExcel(file);

            if(readResult.size()==0)
            {
                return  BaseDTO.createBaseDTO().setSuccess(false).setMessage("upload_faild");
            }
            List<Warehouse> warehouses = new ArrayList<>();
            StringBuilder errmsg = new StringBuilder();
            int i = 2;
            List<Site> sites =new ArrayList<>();
            Set<String> siteNames= readResult.stream().map(r->StringUtils.trim(r[5])).collect(Collectors.toSet());
            if(siteNames.size()>0){
                sites = siteRepository.findByNames(siteNames);
            }
            for (String[] w : readResult) {
                try{
                    Warehouse uname = warehouseRepository.findFirstByHouseNameAndDeletedFlagIsFalse(w[0]);
                    if(uname!=null){
                        errmsg.append(i-1).append(",");
                    }else {

                        Warehouse warehouse = new Warehouse();
                        i++;
                        warehouse.setHouseName(w[0]);
                        warehouse.setAddress(w[1]);
                        warehouse.setLng(new BigDecimal(w[2]));
                        warehouse.setLat(new BigDecimal(StringUtils.trim(w[3])));
                        warehouse.setRadius(new BigDecimal(StringUtils.trim(w[4])));
                        if(StringUtils.isNotBlank(w[5]))
                        {
                            Site site = sites.stream().filter(s -> s.getSiteName().equals(StringUtils.trim(w[5]))).findFirst().orElse(new Site());
                            warehouse.setSiteId(site.getId());
                        }

                        warehouse.setManagerName(w[6]);
                        warehouse.setManagerPhone(w[7]);
                        warehouse.setHousePhone(w[8]);

                        warehouse.setEnableFlag(true);
                        warehouse.setDeletedFlag(false);
                        warehouses.add(warehouse);
                    }

                }catch (Exception e){
                    errmsg.append(i-1).append(",");
                }

            }
            if(warehouses.size()>0)
            {
                warehouseRepository.save(warehouses);
            }
            String msg = "";
            if(errmsg.length()>0)
            {
                //msg = org.apache.commons.lang3.StringUtils.truncate(errmsg.toString(),errmsg.length()-1);
                return  BaseDTO.createBaseDTO().setSuccess(false).setMessage("partial_upload_faild");
            }
        } catch (IOException e) {
            throw new BaseAppException(false,"upload_faild");
        }
        return BaseDTO.createBaseDTO().setSuccess(true);
    }
}
